package xyz.kongbai121.modules.sys.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import xyz.kongbai121.common.redis.serializer.DictInitCacheRunner;
import xyz.kongbai121.common.utils.PageUtils;
import xyz.kongbai121.common.utils.Query;
import xyz.kongbai121.common.utils.Result;
import xyz.kongbai121.common.utils.tree.TreeUtils;
import xyz.kongbai121.modules.sys.dao.SysDictDataDao;
import xyz.kongbai121.modules.sys.dao.SysDictTypeDao;
import xyz.kongbai121.modules.sys.entity.DictData;
import xyz.kongbai121.modules.sys.entity.DictType;
import xyz.kongbai121.modules.sys.entity.SysDictDataEntity;
import xyz.kongbai121.modules.sys.service.SysDictDataService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;


@Service("sysDictDataService")
public class SysDictDataServiceImpl extends ServiceImpl<SysDictDataDao, SysDictDataEntity> implements SysDictDataService {

    @Autowired
    private SysDictDataDao baseDao;
    @Autowired
    private SysDictTypeDao dictTypeDao;
    @Autowired
    private DictInitCacheRunner cacheRunner;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysDictDataEntity> page = this.page(
                new Query<SysDictDataEntity>().getPage(params),
                getWrapper(params)
        );

        return new PageUtils(page);
    }

    private QueryWrapper<SysDictDataEntity> getWrapper(Map<String, Object> params) {
        Long dictTypeId = (Long) params.get("dictTypeId");
        String dictLabel = (String) params.get("dictLabel");
        Integer dictValue = (Integer) params.get("dictValue");

        QueryWrapper<SysDictDataEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(dictTypeId != null, "dict_type_id", dictTypeId);
        wrapper.like(StringUtils.isNotBlank(dictLabel), "dict_label", dictLabel);
        wrapper.eq(dictValue != null && dictValue != 0, "dict_value", dictValue);
        wrapper.orderByDesc("sort", "create_time");
        return wrapper;
    }

    @Override
    public List<DictType> getAllList() {
        List<DictType> typeList = baseDao.getDictTypeList();

        List<DictData> dataList = TreeUtils.build(baseDao.getDictDataList());

        for (DictType type : typeList) {
            for (DictData data : dataList) {
                if (type.getId().equals(data.getDictTypeId())) {
                    type.getDataList().add(data);
                }
            }
        }
        return typeList;
    }

    @Override
    public List<SysDictDataEntity> dataByType(Map<String, Object> params) {
        String dictType = String.valueOf(params.get("dictType"));
        String dictValue = (String) params.get("dictValue");
        if (StringUtils.isNotBlank(dictType)) {
            List<SysDictDataEntity> list = new ArrayList<>();

            if (StringUtils.isNotBlank(dictValue)) {
                String dictLabel = cacheRunner.getDictNameByDictValue(dictType, dictValue);
                SysDictDataEntity dict = new SysDictDataEntity();
                dict.setDictValue(Integer.valueOf(dictValue));
                dict.setDictLabel(dictLabel);
                list.add(dict);
                return list;
            }
            Map<String, Object> dictMaps = cacheRunner.getDictNameByDictValue(dictType);
            if (MapUtil.isNotEmpty(dictMaps)) {
                dictMaps.forEach((key, value) -> {
                    if (StringUtils.isNotBlank(key)) {
                        SysDictDataEntity dict = new SysDictDataEntity();
                        dict.setDictValue(Integer.valueOf(key));
                        dict.setDictLabel(value.toString());
                        list.add(dict);
                    }
                });
            }
            return list;
        }
        return baseDao.dataByType(params);
    }


    @Override
    public SysDictDataEntity getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    public boolean save(SysDictDataEntity entity) {
        setToCache(entity);
        return super.save(entity);
    }

    @Override
    public boolean updateById(SysDictDataEntity entity) {
        setToCache(entity);
        return super.updateById(entity);
    }

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        if (super.removeByIds(idList)) {
            cacheRunner.initDictData();
            return true;
        }
        return false;
    }

    private void setToCache(SysDictDataEntity entity) {
        //存Redis
        Optional.ofNullable(dictTypeDao.selectById(entity.getDictTypeId())).ifPresent(dict -> {
            if (entity.getId() != null) {
                //修改时要先将原先键值删除
                cacheRunner.clearDictData(dict.getDictType(), String.valueOf(baseDao.selectById(entity.getId()).getDictValue()));
            }
            cacheRunner.setDictData(dict.getDictType(), String.valueOf(entity.getDictValue()), entity.getDictLabel());
        });
    }

    @Override
    public Result refresh() {
        cacheRunner.initDictData();
        return Result.ok();
    }

}